package cn.mazexal.exambg.controller.common;

import cn.mazexal.exambg.common.UserTokenManager;
import cn.mazexal.exambg.common.anno.PermitGuest;
import cn.mazexal.exambg.common.models.SingleResponse;
import com.alibaba.fastjson2.JSON;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;


import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

/**
 * @author: Mazexal
 * Date: 2021/9/22
 */
@Slf4j
public class UserTokenInterceptor implements HandlerInterceptor {

    private AntPathMatcher antPathMatcher = new AntPathMatcher();

    private List<String> beforeLoginUrls = new ArrayList<>();

    private List<String> endsWithList = new ArrayList<>();

    private static final Logger LOGGER = LoggerFactory.getLogger(UserTokenInterceptor.class);

    public static final String LOGIN_TOKEN_KEY = "X-EM-Token";

    public UserTokenInterceptor() {
        beforeLoginUrls.add("");
        beforeLoginUrls.add("/");
        beforeLoginUrls.add("/user/**");

        beforeLoginUrls.add("/resource/**");

        beforeLoginUrls.add("/view/**");
        beforeLoginUrls.add("/error");
        beforeLoginUrls.add("/tmp/**");
        beforeLoginUrls.add("/images/**");
        beforeLoginUrls.add("/other/**");
        beforeLoginUrls.add("/appUpdate/**");
//        beforeLoginUrls.add("/admin/**");
//        beforeLoginUrls.add("/common/**");
        beforeLoginUrls.add("/resourceOutLogin/**");

        endsWithList.add(".js");
        endsWithList.add(".css");
        endsWithList.add(".png");
        endsWithList.add(".jpg");
        endsWithList.add(".jpeg");
        endsWithList.add(".svg");
        endsWithList.add(".gif");
        endsWithList.add(".woff");
        endsWithList.add(".ttf");
        endsWithList.add(".ico");
    }

    private boolean isBeforeLogin(String reqPath) {
        for (String url : beforeLoginUrls) {
            if (antPathMatcher.match(url, reqPath)) {
                return true;
            }
        }
        for (String s : endsWithList) {
            if (reqPath.endsWith(s)) {
                return true;
            }
        }
        return false;
    }

    private void returnJson(ServletResponse response) {
        PrintWriter writer = null;
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        try {
            writer = response.getWriter();
            SingleResponse gsonView = SingleResponse.error("500","已过期");
            gsonView.setTimeOut(true);
            writer.print(JSON.toJSONString(gsonView));
        } catch (IOException e) {
            LOGGER.error("拦截器输出流异常 : " + e);
        } finally {
            if (writer != null) {
                writer.flush();
                writer.close();
            }
        }
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String reqPath = request.getServletPath();
        //Thread.sleep(2000);
        if (handler instanceof HandlerMethod) {
            if (((HandlerMethod) handler).getMethod().isAnnotationPresent(PermitGuest.class)) {
                // 访客接口，直接放行
                return true;
            }
        }

        if (isBeforeLogin(reqPath)) {
            //这里是不需要检查的接口以及资源
            return true;
        } else {
            log.info("请求路径:{},请求参数:{}", reqPath, JSON.toJSONString(request.getParameterMap()));
            String token = request.getHeader(LOGIN_TOKEN_KEY);
            if (StringUtils.isBlank(token)) {
                Long userId = (Long) request.getSession().getAttribute("userId");
                if (userId != null && userId > 0) {
                    request.getSession().setAttribute("userId", userId);
                    return true;
                } else {
                    returnJson(response);
                    return false;
                }
            }
            if (!"null".equals(token)) {
                Long userId = UserTokenManager.getUserId(token);
                if (userId == null) {
                    returnJson(response);
                } else {
                    return true;
                }
            }
        }
        return true;
    }

}
